<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="author" content="lijinbo" />
    <title>Document</title>
  </head>
  <body>
    <script id="src">
      class Middleware {
        constructor() {
          // 中间件集合
          this.mids = []
        }
        use(midFn) {
          this.mids.push(midFn)
        }
        run() {
          let index = 0
          const midHandler = async () => {
            const next = async () => {
              index++
              if (this.mids[index]) {
                await midHandler()
              }
            }
            if (this.mids[index]) {
              await this.mids[index](next)
            }
          }
          return midHandler()
        }
      }

      const sleep = (t = 0) => new Promise((a) => setTimeout(a, t))

      // 实例化对象
      const app = new Middleware()

      app.use(async function (next) {
        console.log(1)
        await sleep(500)
        await next()
        console.log(6)
      })
      app.use(async function (next) {
        console.log(2)
        await next()
        console.log(5)
      })
      app.use(async function (next) {
        console.log(3)
        await sleep(800)
        await next()
        console.log(4)
      })

      app.run()

      /**
       * 执行顺序梳理
       * 1 next 6           => next = 2 next 5
       * 1 2 next 5 6       => next = 3 next 4
       * 1 2 3 next 4 5 6   => next = undefined
       * 1 2 3 4 5 6        => 真实的执行顺序
       */
    </script>
  </body>
</html>
